// echo aux function only, should not compile alone.
// -r:"../../Backend/System.IO.FileSystem.dll"

//! 编译方法，目前来说只能是自己改上面那行字，把缺的东西都补齐，之后送命令提示符或者用python脚本编译。
//! windows就是一坨shit……连通配符都不支持……不然我至少能写出类似 dotnet C:\Program Files\dotnet\sdk\*\Roslyn\bincore\csc.dll 这样的语法

// -r:"../../The Scroll of Taiwu_Data/Managed/Mono.Cecil.dll" -r:"../../The Scroll of Taiwu_Data/Managed/System.Core.dll"   -r:"../../The Scroll of Taiwu_Data/Managed/System.Composition.AttributedModel.dll" -r:"../../Backend/System.Runtime.dll"
/**
 *  Everyone's Unity Game Plugin
 *  Copyright (C) 2022 Neutron3529
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
//! 这是一个自带文档注释的Mod，虽然代码很shit，但里面有不少注释，或许会对之后准备玩过月逻辑的人有帮助。
//! 所有文档注释会用//!开头，请注意搜索
//! 首先是前后端，前端对后端的调用会先被塞进 ProcessMethodCall，之后分发给对应domain的CallMethod，由CallMethod进行进一步的分发。借助这一点，我们可以快速找到前端调用究竟是在使用哪个函数。
using System;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Collections.Generic;
using static Utils.Logger;

using Config.EventConfig;
using GameData.Domains.TaiwuEvent;
using GameData.Domains.TaiwuEvent.Enum;

namespace Neutron3529.ChaosEvents {
    public partial class ChaosEvents : EventPackage {
        public 大夫.大夫 E07(){
            var o=new 大夫.大夫();
            {
                var taiwuEvent = GameData.Domains.DomainManager.TaiwuEvent.GetEvent("fb38f657-6ed0-41e4-a0c2-c82afb49762f"); // @人物互动-恩义互动
                var lst=taiwuEvent.EventConfig.EventOptions.ToList();
                for(int i=0;i<o.EventOptions.Length-1/*其他话题*/;i++){
                    lst.Insert(lst.Count-1, o.EventOptions[i]);
                }
                taiwuEvent.EventConfig.EventOptions=lst.ToArray();
            }
            return o;
        }
    }
    namespace 大夫 {
        public class 大夫 : EventItem {
            UnfairTrue Random=new UnfairTrue();
            public 大夫() :base("Prof.大夫", "70b4d45d-ba15-423d-b94e-b40e348eb9c7", "“瞧一瞧看一看，正宗祖传大力丸\n男的吃了女的受不了，女的吃了男的受不了，男女都吃床受不了……”\n{0}听{1}如此吹嘘，神色有些不悦：\n“这玩意灵嘛？”\n{1}笑了笑，悄悄对{0}说，“你找个人试试，不灵不要钱。”\n\n<color=#lightgrey>（唆使{0}选取地格中的一个倒霉鬼试药）</color>"){
                this.EventOptions = new TaiwuEventOption[2];//（出售药丸……）/（便是此人了……） （其他话题……）
                for(int i=0;i<this.EventOptions.Length;i++){
                    var op=new TaiwuEventOption {
                        OptionKey = "Option_352907"+(i+1).ToString("02"),
                        OnOptionSelect = new Func<string>(this.OnOptionSelect(i)),
                        OnOptionVisibleCheck = new Func<bool>(this.OnCheckOptionCondition(i)),
                        OnOptionAvailableCheck = new Func<bool>(this.OnCheckEventCondition),
                        GetReplacedContent = new Func<string>(this.Desc(i)),
                        GetExtraFormatLanguageKeys = new Func<List<string>>(this.GetExtraFormatLanguageKeys)
                    };
                    this.EventOptions[i]=op;
                }
            }

            public override string EventContent()=>string.Format(this.content, Name(this.ArgBox.GetCharacter("CharacterId")), Name(GameData.Domains.DomainManager.Taiwu.GetTaiwu()));
            private Func<bool> OnCheckOptionCondition(int index){
                switch(index){
                    default: return ()=>{
                        var pd=GameData.Domains.TaiwuEvent.EventHelper.EventHelper.GetCurrentProfessionData();
                        var character=this.EventOptions[index].ArgBox.GetCharacter("CharacterId");
                        if(character!=null && pd!=null){
                            var location=character.GetLocation();
                            if(location.IsValid()){
                                var blck=GameData.Domains.DomainManager.Map.GetBlock(location);
                                return GameData.Domains.Character.AgeGroup.GetAgeGroup((character.GetCurrAge()))>0 && pd.TemplateId == 13 && blck!=null && blck.CharacterSet!=null;
                            }
                        }
                        return false;
                    };
                }
            }
            public override void OnEventEnter(){
                var character=this.ArgBox.GetCharacter("CharacterId");
                var blck=GameData.Domains.DomainManager.Map.GetBlock(character.GetLocation());
                var lst=new List<int>();
                var tmp=character;
                if(blck!=null && blck.CharacterSet!=null){
                    foreach(var x in blck.CharacterSet.Union(GameData.Domains.DomainManager.Taiwu.GetGroupCharIds().GetCollection())){
                        if(x!=character.GetId() && GameData.Domains.DomainManager.Character.TryGetElement_Objects(x, out tmp) && GameData.Domains.Character.AgeGroup.GetAgeGroup((tmp.GetCurrAge()))>0){
                            lst.Add(x);
                        }
                    }
                }
                // var lst=(from x in GameData.Domains.DomainManager.Map.GetBlock(character.GetLocation()).CharacterSet where x!=character.GetId() select x).ToList();
                GameData.Domains.TaiwuEvent.EventHelper.EventHelper.SelectCharacterFromCharIdList(this.ArgBox, "CharacterId2", lst);
            }
            static FieldInfo _fertility=typeof(GameData.Domains.Character.Character).GetField("_fertility",(BindingFlags)(-1));
            private unsafe Func<string> OnOptionSelect(int index){
                switch(index){
                    case 0:return ()=>{
                        if(this.EventOptions[index].ArgBox.Contains<bool>("NeutronFlag")){//重入branch
                            this.ArgBox.Remove<bool>("NeutronFlag");
                            var character=this.ArgBox.GetCharacter("CharacterId");
                            var cname=Name(character);
                            var tname=Name(GameData.Domains.DomainManager.Taiwu.GetTaiwu());
                            var c2=this.ArgBox.GetCharacter("CharacterId2");
                            this.ArgBox.Remove<int>("CharacterId2");
                            var c2n=Name(c2);
                            var currDate=GameData.Domains.DomainManager.World.GetCurrDate();
                            var location=character.GetLocation();
                            var lifeRecordCollection = GameData.Domains.DomainManager.LifeRecord.GetLifeRecordCollection();
                            string outcome="";
                            var motherId=character.GetGender()!=0?c2.GetId():character.GetId();
                            // 如下操作是无效的。因为设定特性会影响生育率缓存，于是_fertility的缓存值一定不会被使用。
                            // var ffert=character.GetFertility();//预先刷新防止缓存修正我们的临时更改
                            // var sfert=c2.GetFertility();//预先刷新防止缓存修正我们的临时更改
                            // _fertility.SetValue(character,(short)32765); // 保证怀孕
                            // _fertility.SetValue(c2,(short)32765); // 保证怀孕
                            {
                                var rng=this.context.Random;
                                this.context.Random=this.Random;

                                GameData.Domains.Character.PregnantState pregnantState;
                                if (!GameData.Domains.DomainManager.Character.TryGetPregnantState(motherId, out pregnantState)){
                                    GameData.Domains.DomainManager.Character.RemovePregnantLock(context, motherId);
                                } else {
                                    if(motherId==character.GetId()){
                                        outcome=$"\n\n<color=#lightgrey>（尽管{cname}已是孕妇，但在药力的作用下，{cname}仍旧不住求欢）</color>";
                                    } else {
                                        outcome=$"\n\n<color=#lightgrey>（{cname}在药力的作用下，并没有意识到{c2n}是孕妇这个事实）</color>";
                                    }
                                }
                                character.MakeLove(this.context,c2,character.GetGender()!=0); // 没吃药一方丧失冠姓权.gif
                                // character.GetGender()!=0, rape=true, 此时吃药的是女方，孩子随女方姓
                                // character.GetGender()==0, rape=false, 此时孩子随男方姓
                                // 这里注释掉ml行为，将其放在最后，以此保证太吾的血亲系统不出BUG

                                this.context.Random=rng;
                                lifeRecordCollection.AddRapeSucceed(character.GetId(), currDate, c2.GetId(), location);
                            }
                            // 没必要恢复，因为之前已经恢复了
                            // _fertility.SetValue(character,ffert); // 恢复更改
                            // _fertility.SetValue(c2,sfert);
                            var blck=GameData.Domains.DomainManager.Map.GetBlock(character.GetLocation());
                            var lst=new List<int>();
                            var tmp=character;
                            if(blck!=null && blck.CharacterSet!=null){
                                foreach(var x in blck.CharacterSet){
                                    if(x!=character.GetId() && GameData.Domains.DomainManager.Character.TryGetElement_Objects(x, out tmp) && GameData.Domains.Character.AgeGroup.GetAgeGroup((tmp.GetCurrAge()))>0){
                                        lst.Add(x);
                                    }
                                }
                            }
                            for(int i=0;i<10;i++){
                                if(lst.Count>0 && GameData.Domains.DomainManager.Character.TryGetElement_Objects(lst[this.context.Random.Next(lst.Count)], out var c3)){
                                    character.MakeLove(this.context,c3,true);
                                    lifeRecordCollection.AddRapeSucceed(character.GetId(), currDate, c3.GetId(), location);
                                } else {
                                    lifeRecordCollection.AddRapeSucceed(c2.GetId(), currDate, character.GetId(), location);
                                }
                            }
                            character.MakeLove(this.context,c2,character.GetGender()!=0);
                            if(outcome.Length==0 && GameData.Domains.DomainManager.Character.TryGetPregnantState(motherId, out var _)){
                                outcome="\n\n<color=#lightgrey>（"+(character.GetGender()!=0?c2n:cname)+(character.GetGender()!=0?"因为"+cname+"的粗暴行为怀上了孩子，为此后悔不已。":"怀上了"+c2n+"的孩子")+"）</color>";
                            }
                            // var outcome=character.GetGender()!=0?$"{cname}在误服药丸之后欲火焚身，与许多人欢好，直到{c2n}因为体力不支昏了过去。{c2n}并未在这场狂风骤雨之中感到多少愉悦，她只希望一切":$"{cname}在误服药丸之后欲火焚身，与许多人欢好，却终究意尤未满。一阵阵荒唐之后，终究是连欢好的对象，都忘了个干干净净";
                            return Goto($"“试试就试试，怕你不成？”\n{tname}只见{cname}跑到{c2n}面前，掏出了药丸……\n不料{c2n}反应迅速，一抬手，反把药丸喂进{cname}口中\n\n<s>之后发生的事情过于残暴，需要一个大手子提供文本</s>"+outcome,character.GetGender()!=0?"（如此甚好……）":"（焉知非福……）",index);
                        } else {//初入branch
                            this.EventOptions[index].ArgBox.Set("NeutronFlag",false);
                            return this.guid;//重入
                        }
                    };
                    case 1:return ()=>{
                        this.EventOptions[index].ArgBox.Remove<bool>("NeutronFlag");
                        return "fb38f657-6ed0-41e4-a0c2-c82afb49762f"; // @人物互动-恩义互动
                    };
                    default: return ()=>string.Empty;
                }
            }
            public override Func<string> Desc(int index){
                switch(index){
                    case 0:
                        return ()=>{
                            return this.EventOptions[index].ArgBox.Contains<bool>("NeutronFlag")?"（便是此人了……）":"（出售药丸……）";
                        };
                    case 1:
                        return ()=>{
                            return "（其他话题……）";
                        };
                    default: return ()=>string.Empty;
                }
            }
        }
    }
}
